Team Members: Fucheng Yao, Huaiping Wang, Limei Huang, Eman Nagib, Kwangwoo Kim

Gaming Data Overview and Backgrond Knowledge

1.Brief description and data soure

The gaming data set has information of video games with sales greater than 100,000 copies since the year 1980 to 2016. This gaming data set is downloaded from Kaggle.com.

Mobile, PC/Mac(computer), social/online, and console are common gaming platforms. Console here refers to a computer device that outputs a video signal or visual image to display a video game that one or more people can play. Some popular consoles are PlayStation 4 Pro, Xbox One X, Nintendo Switch. Our dataset is about videogames played on console only.


2.Data Cleaning
  • We \(\color{red}{\text{removed}}\) all NULL values, Unknown values, and data in 2017 or later.
  • We \(\color{red}{\text{converted}}\) Year from String to Numeric.
  • We \(\color{red}{\text{added}}\) a new column called Portable based on if the gaming console is portable or not.
  • We have 16187 rows and 12 variables after cleaning the data and adding the Portable variable.
options(stringsAsFactors = FALSE)
Portable <- function(df) {
 len <- length(df$Platform)
 new_vec <- vector(mode = "numeric", length = len)
 protvec <- c("DS", "GB", "3DS", "GBA")
 for (i in 1:len)  {
   if (df$Platform[i] %in% protvec) {
     new_vec[i] <- 1
   } else {
     new_vec[i] <- 0
   }
 }
 return(new_vec)
}

3.Variables
Variable Description
Rank Ranking of overall sales
Name The games name
Platform Platform of the games release (i.e. PC,PS4, etc.)
Year Year of the game’s release
Genre Genre - Genre of the game
Publisher Publisher of the game
NA_Sales Sales in North America (in millions)
EU_Sales Sales in Europe (in millions)
JP_Sales Sales in Japan (in millions)
Other_Sales Sales in the rest of the world (in millions)
Global_Sales Total worldwide sales
Portable If the gaming console is portable (1=yes,0=no)

4.Glimpse of Data
a.
Classes ‘spec_tbl_df’, ‘tbl_df’, ‘tbl’ and 'data.frame':    16187 obs. of  12 variables:
 $ Rank        : num  3825 1679 1879 1711 638 ...
 $ Name        : chr  "Seaman" "NFL 2K" "NFL 2K1" "Shenmue" ...
 $ Platform    : chr  "DC" "DC" "DC" "DC" ...
 $ Year        : num  1999 1999 2000 1999 1998 ...
 $ Genre       : chr  "Simulation" "Sports" "Sports" "Adventure" ...
 $ Publisher   : chr  "Sega" "Sega" "Sega" "Sega" ...
 $ NA_Sales    : num  0 1.12 1.02 0.52 1.26 1.1 0.41 0 0 0 ...
 $ EU_Sales    : num  0 0.05 0.05 0.24 0.61 0.51 0.23 0 0 0 ...
 $ JP_Sales    : num  0.52 0 0 0.38 0.46 0.12 0.47 1.01 0.54 0.62 ...
 $ Other_Sales : num  0 0.02 0.02 0.04 0.08 0.08 0.03 0 0 0 ...
 $ GLobal_Sales: num  0.52 1.2 1.09 1.18 2.42 1.81 1.14 1.01 0.54 0.62 ...
 $ Portable    : num  0 0 0 0 0 0 0 1 1 1 ...
b. 31 unique platforms:

DC, DS, GB, GC, PC, PS, WS, XB, 3DS, GBA, GEN, N64, NES, PS2, PS3, PS4, PSP, PSV, SAT, SCD, Wii, 2600, SNES, WiiU, X360, XOne, NG, 3DO, TG16, GG, PCFX

c. 12 unique genres:

Simulation, Sports, Adventure, Platform, Racing, Action, Misc, Role-Playing, Puzzle, Fighting, Strategy, Shooter

d. 575 unique publishers:

Top 10 Publishers based on frequency: Electronic Arts, Activision, Namco Bandai Games, Ubisoft, Konami Digital Entertainment, THQ, Nintendo, Sony Computer Entertainment, Sega, Take-Two Interactive


Problem Set: Where and how to invest in the gaming industry


3 Investment options and recommendations

3.a Global sales proportion by region
  • For the most part we see that the North America accounts for the highest proportion of global sales. We can also see that European sales are on an incline and actually surpass North american sales by the year 2015-2016. Even though Japan’s proportion of Global sales seem to be declining in the past years, for the most recent years it seems to be steadily inclining.
games <- read_csv("games.csv") 
df_trial <- data_frame(sort(games$Year), NA_Sales = games$NA_Sales, games$EU_Sales,
                      games$JP_Sales, games$Other_Sales, games$GLobal_Sales)
games3 <- games %>%
 select(Year, NA_Sales, EU_Sales, JP_Sales, Other_Sales,GLobal_Sales) %>%
 group_by(Year) %>%
 summarise(NA_sales_prop = sum(NA_Sales)/sum(GLobal_Sales),
           EU_sales_prop = sum(EU_Sales)/sum(GLobal_Sales),
           JP_sales_prop = sum(JP_Sales)/sum(GLobal_Sales),
           Other_sales_prop = sum(Other_Sales)/sum(GLobal_Sales),
           Global_sales_prop = sum(GLobal_Sales)/sum(GLobal_Sales))
mycolors <- c("#771C19", "#AA3929", "#8E9CA3", "#556670", "#000000", "#E25033", "#F27314", "#F8A31B", "#E2C59F", "#B6C5CC")
regions <- c( "darkgreen" = "North America", "blue" = "Europe" ,  "sienna" = "Japan" , "orange" = "Other Regions", "black" = "Global")

ggplot(games3,aes(x=Year))+
  geom_line(aes(y = NA_sales_prop ,color = "#771C19"))+
  geom_line(aes(y = EU_sales_prop , color = "#B6C5CC"))+
  geom_line(aes(y = JP_sales_prop, color = "#E25033" ))+
  geom_line(aes(y = Other_sales_prop, color = "#E2C59F"))+
  geom_line(aes(y = Global_sales_prop, color = "black"))+
  labs(title = "Sales per region from 1980-2016", y = "Percentage of global sales")+
  scale_color_manual(name = "Regions", values = c( "darkgreen", "blue", "sienna" , "orange", "black"),labels=c("North America", "Europe" , "Japan" , "Other Regions", "Global"))

3.b Summary
Option North America Europe Japan
Publisher Nintendo Nintendo Nintendo
Platform X360 PS3 DS
Genre Action Action Role-Playing

Appendix

Data Exploration.
ggplot(games, aes(x=Year, fill=..count..)) +
    geom_bar()+
    scale_color_gradient(low="#771C19", high= "#F27314")+
    scale_fill_gradient(low="#771C19", high= "#F27314")+
    labs(title="Number of Games Released every Year", x= "Year", 
         y= "Total Number of Games")+
    geom_text(stat='count',aes(label=..count..), hjust=-0.1,color="black", size=2.5)+
    scale_x_continuous(breaks = 1980:2016) + theme_minimal()+
  coord_flip()

Data Exploration 2

Data Exploration 3
ok <- games %>% select(Year,GLobal_Sales,Genre)%>%group_by(Year,Genre)%>%
  summarise(Total_sales=sum(GLobal_Sales)) 
ok1 <- arrange(ok, desc(Year))

plot_ly(ok1, x = ~Total_sales, y = ~Genre, z = ~Year) %>% layout( title ="Sales by genre from 1980 - 2016") %>%
  add_markers(color = ~Genre, size = 0.5)
LS0tCnRpdGxlOiAiVGVhbSA1IEdhbWluZyBEYXRhIE5vdGVib29rIgpzdWJ0aXRsZTogIiFbXShnYW1lMi5wbmcpe3dpZHRoPTI1MH0iCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KKipUZWFtIE1lbWJlcnM6IEZ1Y2hlbmcgWWFvLCBIdWFpcGluZyBXYW5nLCBMaW1laSBIdWFuZywgRW1hbiBOYWdpYiwgS3dhbmd3b28gS2ltKiogCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQojIGxvYWRpbmcgbGlicmFyaWVzCmxpYnJhcnkoRFQpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeShwbG90bHkpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkod2VzYW5kZXJzb24pCmdhbWVzIDwtIHJlYWRfY3N2KCJnYW1lcy5jc3YiKSAKbXljb2xvcnMgPC0gYygiIzc3MUMxOSIsICIjQUEzOTI5IiwgIiM4RTlDQTMiLCAiIzU1NjY3MCIsICIjMDAwMDAwIiwgIiNFMjUwMzMiLCAiI0YyNzMxNCIsICIjRjhBMzFCIiwgIiNFMkM1OUYiLCAiI0I2QzVDQyIpCgojIG1vZGlmeWluZyBjaGFydCBzaXplCm9wdGlvbnMocmVwci5wbG90LndpZHRoPTI1MCwgcmVwci5wbG90LmhlaWdodD0xMDApCmBgYAoKCiMjIyBHYW1pbmcgRGF0YSBPdmVydmlldyBhbmQgQmFja2dyb25kIEtub3dsZWRnZQojIyMjIyAxLkJyaWVmIGRlc2NyaXB0aW9uIGFuZCBkYXRhIHNvdXJlClRoZSBnYW1pbmcgZGF0YSBzZXQgaGFzIGluZm9ybWF0aW9uIG9mIHZpZGVvIGdhbWVzIHdpdGggc2FsZXMgZ3JlYXRlciB0aGFuIDEwMCwwMDAgY29waWVzIHNpbmNlIHRoZSB5ZWFyIDE5ODAgdG8gMjAxNi4gVGhpcyBbZ2FtaW5nIGRhdGEgc2V0XShodHRwczovL3d3dy5rYWdnbGUuY29tL2dyZWdvcnV0L3ZpZGVvZ2FtZXNhbGVzKSBpcyBkb3dubG9hZGVkIGZyb20gW0thZ2dsZS5jb21dKHd3dy5rYWdnbGUuY29tKS4KCk1vYmlsZSwgUEMvTWFjKGNvbXB1dGVyKSwgc29jaWFsL29ubGluZSwgYW5kIGNvbnNvbGUgYXJlIGNvbW1vbiBnYW1pbmcgcGxhdGZvcm1zLiBDb25zb2xlIGhlcmUgcmVmZXJzIHRvIGEgY29tcHV0ZXIgZGV2aWNlIHRoYXQgb3V0cHV0cyBhIHZpZGVvIHNpZ25hbCBvciB2aXN1YWwgaW1hZ2UgdG8gZGlzcGxheSBhIHZpZGVvIGdhbWUgdGhhdCBvbmUgb3IgbW9yZSBwZW9wbGUgY2FuIHBsYXkuIFNvbWUgcG9wdWxhciBjb25zb2xlcyBhcmUgUGxheVN0YXRpb24gNCBQcm8sIFhib3ggT25lIFgsIE5pbnRlbmRvIFN3aXRjaC4gT3VyIGRhdGFzZXQgaXMgYWJvdXQgdmlkZW9nYW1lcyBwbGF5ZWQgb24gY29uc29sZSBvbmx5LiAgCgotLS0KCiMjIyMjIDIuRGF0YSBDbGVhbmluZyAKKiBXZSAkXGNvbG9ye3JlZH17XHRleHR7cmVtb3ZlZH19JCBhbGwgKipOVUxMKiogdmFsdWVzLCAqKlVua25vd24qKiB2YWx1ZXMsIGFuZCBkYXRhIGluICoqMjAxNyBvciBsYXRlcioqLgoqIFdlICRcY29sb3J7cmVkfXtcdGV4dHtjb252ZXJ0ZWR9fSQgWWVhciBmcm9tICoqU3RyaW5nKiogdG8gKipOdW1lcmljKiouIAoqIFdlICRcY29sb3J7cmVkfXtcdGV4dHthZGRlZH19JCBhIG5ldyBjb2x1bW4gY2FsbGVkICpQb3J0YWJsZSogYmFzZWQgb24gaWYgdGhlIGdhbWluZyBjb25zb2xlIGlzIHBvcnRhYmxlIG9yIG5vdC4KKiBXZSBoYXZlIGByIG5yb3coZ2FtZXMpYCByb3dzIGFuZCBgciBuY29sKGdhbWVzKWAgdmFyaWFibGVzIGFmdGVyIGNsZWFuaW5nIHRoZSBkYXRhIGFuZCBhZGRpbmcgdGhlICpQb3J0YWJsZSogdmFyaWFibGUuIAoKYGBge3IgZWNobz1UUlVFfQpvcHRpb25zKHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKUG9ydGFibGUgPC0gZnVuY3Rpb24oZGYpIHsKIGxlbiA8LSBsZW5ndGgoZGYkUGxhdGZvcm0pCiBuZXdfdmVjIDwtIHZlY3Rvcihtb2RlID0gIm51bWVyaWMiLCBsZW5ndGggPSBsZW4pCiBwcm90dmVjIDwtIGMoIkRTIiwgIkdCIiwgIjNEUyIsICJHQkEiKQogZm9yIChpIGluIDE6bGVuKSAgewogICBpZiAoZGYkUGxhdGZvcm1baV0gJWluJSBwcm90dmVjKSB7CiAgICAgbmV3X3ZlY1tpXSA8LSAxCiAgIH0gZWxzZSB7CiAgICAgbmV3X3ZlY1tpXSA8LSAwCiAgIH0KIH0KIHJldHVybihuZXdfdmVjKQp9CgpgYGAKCmBgYHtyfQpnYW1lcyRQb3J0YWJsZSA8LSBQb3J0YWJsZShnYW1lcykKYGBgCgotLS0KCiMjIyMjIDMuVmFyaWFibGVzIAp8IFZhcmlhYmxlICAgfCAgICAgIERlc2NyaXB0aW9uICAgICAgfAp8LS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLTp8CnwgUmFuayB8ICBSYW5raW5nIG9mIG92ZXJhbGwgc2FsZXMgfCAKfCBOYW1lIHwgICAgVGhlIGdhbWVzIG5hbWUgICB8ICAgCnwgUGxhdGZvcm0gfCBQbGF0Zm9ybSBvZiB0aGUgZ2FtZXMgcmVsZWFzZSAoaS5lLiBQQyxQUzQsIGV0Yy4pIHwgICAgCnwgWWVhciB8IFllYXIgb2YgdGhlIGdhbWUncyByZWxlYXNlIHwKfCBHZW5yZSB8IEdlbnJlIC0gR2VucmUgb2YgdGhlIGdhbWUgfAp8IFB1Ymxpc2hlciB8UHVibGlzaGVyIG9mIHRoZSBnYW1lIHwKfE5BX1NhbGVzfFNhbGVzIGluIE5vcnRoIEFtZXJpY2EgKGluIG1pbGxpb25zKSB8IAp8IEVVX1NhbGVzfCBTYWxlcyBpbiBFdXJvcGUgKGluIG1pbGxpb25zKSB8CnxKUF9TYWxlcyB8U2FsZXMgaW4gSmFwYW4gKGluIG1pbGxpb25zKSB8CnwgT3RoZXJfU2FsZXN8U2FsZXMgaW4gdGhlIHJlc3Qgb2YgdGhlIHdvcmxkIChpbiBtaWxsaW9ucykgfAp8R2xvYmFsX1NhbGVzfFRvdGFsIHdvcmxkd2lkZSBzYWxlcyB8CnwgUG9ydGFibGUgfCBJZiB0aGUgZ2FtaW5nIGNvbnNvbGUgaXMgcG9ydGFibGUgKDE9eWVzLDA9bm8pIHwKCi0tLQoKIyMjIyMgNC5HbGltcHNlIG9mIERhdGEgCiMjIyMjIyBhLgpgYGB7cn0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBGQUxTRQopCnN0cihnYW1lcyxnaXZlLmF0dHI9RikKYGBgCgoKIyMjIyMjIGIuICoqYHIgbGVuZ3RoKHVuaXF1ZShnYW1lcyRQbGF0Zm9ybSkpYCB1bmlxdWUgcGxhdGZvcm1zOioqICAgIApgciB1bmlxdWUoZ2FtZXMkUGxhdGZvcm0pIGAKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnVuaXF1ZShnYW1lcyRQbGF0Zm9ybSkKYGBgCgoKIyMjIyMjIGMuICoqYHIgbGVuZ3RoKHVuaXF1ZShnYW1lcyRHZW5yZSkpYCB1bmlxdWUgZ2VucmVzOioqICAgCmByIHVuaXF1ZShnYW1lcyRHZW5yZSkgYAoKCiMjIyMjIyBkLiAqKmByIGxlbmd0aCh1bmlxdWUoZ2FtZXMkUHVibGlzaGVyKSlgIHVuaXF1ZSBwdWJsaXNoZXJzOioqIApUb3AgMTAgUHVibGlzaGVycyBiYXNlZCBvbiBmcmVxdWVuY3k6IGByIHRvcF90ZW4oZ2FtZXMpYAoKYGBge3IgaW5jbHVkZT1GQUxTRX0KdG9wX3RlbiA8LSBmdW5jdGlvbih4KSB7CiAgZGZfdGVtcCA8LSBjb3VudCh4LCBQdWJsaXNoZXIsIHNvcnQgPSBUUlVFKQogIHJldHVybihkZl90ZW1wJFB1Ymxpc2hlclsxOjEwXSkKfQpgYGAKCgotLS0KCiMjIyBQcm9ibGVtIFNldDogIFdoZXJlIGFuZCBob3cgdG8gaW52ZXN0IGluIHRoZSBnYW1pbmcgaW5kdXN0cnkgCiogIEdsb2JhbCB0cmVuZHMgYW5kIGFubHlzaXMgCiogIFJlZ2lvbmFsIHRyZW5kcyBhbmQgYW5hbHlzaXMgCiogIEludmVzdG1lbnQgb3B0aW9ucyBhbmQgcmVjb21tZW5kYXRpb25zIAoKCi0tLQojIyMgMS5HbG9iYWwgdHJlbmRzIGFuZCBhbmFseXNpcyAKIyMjIyMjICAxLmEgIFdoYXQgaXMgdGhlIHRvcCBwbGF0Zm9ybSBlYWNoIHllYXI/IAoqIE9uY2UgYSBwbGF0Zm9ybSBjbGlja3MgaW4gdGhlIG1hcmtldCwgaXQgZ29lcyBvbiB0byBydWxlIGZvciBhIGZldyB5ZWFycy4KKiBUaGUgUGxheXN0YXRpb24gcGxhdGZvcm0gd2FzIHBvcHVsYXIgZm9yIG5lYXJseSAyMCB5ZWFycy4KCmBgYHtyIGVjaG89VFJVRSxyZXN1bHRzPUZBTFNFfQoKdG9wX3BsYXRmb3JtcyA8LSBnYW1lcyAlPiUKICAgICAgICAgICAgIGdyb3VwX2J5KFllYXIsIFBsYXRmb3JtKSAlPiUKICAgICAgICAgICAgIHN1bW1hcml6ZShSZXZlbnVlID0gc3VtKEdMb2JhbF9TYWxlcykpICU+JQogICAgICAgICAgICAgYXJyYW5nZShkZXNjKFJldmVudWUpKSAlPiUKICAgICAgICAgICAgIHRvcF9uKDEpCmdncGxvdCh0b3BfcGxhdGZvcm1zLCBhZXMoWWVhciwgUmV2ZW51ZSwgZmlsbCA9IFBsYXRmb3JtKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdndGl0bGUoIlRvcCBQbGF0Zm9ybSBieSBSZXZlbnVlIGVhY2ggeWVhciIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBteWNvbG9ycykrCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4odG9wX3BsYXRmb3JtcyRZZWFyKSxtYXgodG9wX3BsYXRmb3JtcyRZZWFyKSw1KSkrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCmBgYAoKCiMjIyMjIyAgMS5iICBUb3AgMTAgYmVzdCBzZWxsaW5nIHB1Ymxpc2hlcnMgb3ZlciB0aW1lPyAKKiBUb3AgMyBwdWJsaXNoZXJzIGFyZSBOaW50ZW5kbywgRUEsIGFuZCBBY3RpdmlzaW9uLgoKYGBge3IgZWNobz1UUlVFLGZpZy53aWR0aD0xMn0KCnRvcDEwIDwtIGdhbWVzICU+JXNlbGVjdChQdWJsaXNoZXIsR0xvYmFsX1NhbGVzKSU+JWdyb3VwX2J5KFB1Ymxpc2hlciklPiVzdW1tYXJpc2UoR0xvYmFsX1NhbGVzPXN1bShHTG9iYWxfU2FsZXMpKSU+JWFycmFuZ2UoZGVzYyhHTG9iYWxfU2FsZXMpKSU+JWhlYWQoMTApCgoKcCA8LSBnZ3Bsb3QodG9wMTAsIGFlcyh4PXJlb3JkZXIoUHVibGlzaGVyLC1HTG9iYWxfU2FsZXMpLHk9R0xvYmFsX1NhbGVzLCxsYWJlbD1yb3VuZChHTG9iYWxfU2FsZXMsMikpKSArCiBzdGF0X3N1bW1hcnkoZnVuLnk9c3VtLCBnZW9tPSJiYXIiLHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKDEpLHdpZHRoPTAuOCxzaG93LmxlZ2VuZCA9IEYsLGNvbD0iYmxhY2siLGZpbGw9InNreWJsdWUiKSsKbGFicyh0aXRsZSA9ICJUb3AgMTAgYmVzdCBzZWxsaW5nIHB1Ymxpc2hlcnMiLGNhcHRpb24gPSAiU2FsZXMgaW4gTWlsbGlvbiIpKwogICBnZW9tX3RleHQoY29sPSJibGFjayIsc2l6ZT00LHZqdXN0PS0xKSsKICB5bGFiKCJHbG9iYWwgU2FsZXMiKSt4bGFiKCJQdWJsaXNoZXIiKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cl93cmFwKHgsIHdpZHRoID0xKSkKCnAKYGBgCgojIyMjIyMgMS5jICBCZXN0IHNlbGxpbmcgcGxhdGZvcm1zIGZvciB0aGUgVE9QIDMgcHVibGlzaGVycwoqIFRvcCAzIHBsYXRmb3JtcyBmb3IgZWFjaCBwdWJsaXNoZXI6CiogTmludGVuZG86IFdpaSwgR0IsIERTCiogRUE6IFgzNjAsIFBTMywgUFMyCiogQWN0aXZpc2lvbjogWDM2MCwgUFMzLCBQUzIKCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz1GQUxTRSxmaWcud2lkdGg9N30KdG9wX3RocmVlX3B1Ymxpc2hlciA8LSBzdWJzZXQoZ2FtZXMsUHVibGlzaGVyICVpbiUgYygiTmludGVuZG8iLCJFbGVjdHJvbmljIEFydHMiLCJBY3RpdmlzaW9uIikpCnRvcF90aHJlZV9wdWJsaXNoZXIkUG9ydGFibGUgPC0gZmFjdG9yKHRvcF90aHJlZV9wdWJsaXNoZXIkUG9ydGFibGUpCnRvcF90aHJlZV9wdWJsaXNoZXJfcGxhdGZvcm0gPC0gdG9wX3RocmVlX3B1Ymxpc2hlciAlPiVzZWxlY3QoUHVibGlzaGVyLFBsYXRmb3JtLFBvcnRhYmxlLEdMb2JhbF9TYWxlcyklPiVncm91cF9ieShQdWJsaXNoZXIsUGxhdGZvcm0sUG9ydGFibGUpJT4lc3VtbWFyaXNlKEdMb2JhbF9TYWxlcz1zdW0oR0xvYmFsX1NhbGVzKSklPiVhcnJhbmdlKGRlc2MoUHVibGlzaGVyKSkKdG9wX25ldyA8LSB0b3BfdGhyZWVfcHVibGlzaGVyX3BsYXRmb3JtJT4lZ3JvdXBfYnkoUHVibGlzaGVyKSU+JXRvcF9uKDMpCnRvcF9uZXckUHVibGlzaGVyX2YgPSBmYWN0b3IodG9wX25ldyRQdWJsaXNoZXIsIGxldmVscz1jKCJOaW50ZW5kbyIsIkVsZWN0cm9uaWMgQXJ0cyIsIkFjdGl2aXNpb24iKSkKZ2dwbG90KHRvcF9uZXcsIGFlcyh4PVBsYXRmb3JtLCB5PUdMb2JhbF9TYWxlcywgY29sb3I9UHVibGlzaGVyLHNoYXBlPVBvcnRhYmxlKSkgKwogZ2VvbV9wb2ludChzaXplPTMpKwogc2NhbGVfY29sb3JfZGlzY3JldGUoYnJlYWtzPWMoIk5pbnRlbmRvIiwiRWxlY3Ryb25pYyBBcnRzIiwiQWN0aXZpc2lvbiIpKSArCiBsYWJzKHRpdGxlPSIgICAgIFRvcCAzIHBsYXRmb3JtcyBmb3IgdGhlIHRvcCAzIHB1Ymxpc2hlcnMiLGNhcHRpb249IlNhbGVzIGluIE1pbGxpb24iKSArCiBnZW9tX3NlZ21lbnQoYWVzKHg9UGxhdGZvcm0seGVuZD1QbGF0Zm9ybSwgeT0wLCB5ZW5kPUdMb2JhbF9TYWxlcykpKwogZ2VvbV90ZXh0KGFlcyhsYWJlbD1HTG9iYWxfU2FsZXMpLCBoanVzdCA9IC0wLjMsIHNpemUgPSAyLjYsZm9udGZhY2UgPSAiYm9sZCIsY29sb3I9J2JsYWNrJykgKwogdGhlbWUoIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNyxoanVzdD0tMC40KSkgKwogICBmYWNldF93cmFwKH4gUHVibGlzaGVyX2YsIG5yb3cgPSA1LCBzY2FsZXMgPSAnZnJlZScsIHN0cmlwLnBvc2l0aW9uID0gJ3JpZ2h0JykrCiB5bGltKDAsIG1heCh0b3BfbmV3JEdMb2JhbF9TYWxlcyArIDEwKSkreWxhYigiR2xvYmFsIFNhbGVzIikrCiBjb29yZF9mbGlwKCkKYGBgCgojIyMjIyMgMS5kICBCZXN0IHNlbGxpbmcgZ2VucmUgZm9yIHRoZSBUT1AgMyBwdWJsaXNoZXJzCiogVG9wIDMgZ2VucmVzIGZvciBlYWNoIHB1Ymxpc2hlcjoKKiBOaW50ZW5kbzogU3BvcnRzLCBSb2xlLXBsYXlpbmcsIFBsYXRmb3JtCiogRUE6IHNwb3J0cywgc2hvb3RlciwgcmFjaW5nCiogQWN0aXZpc2lvbjogc3BvcnRzLCBzaG9vdGVyLCBhY3Rpb24KCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz1GQUxTRX0KdG9wX3RocmVlX3B1Ymxpc2hlciA8LSBzdWJzZXQoZ2FtZXMsUHVibGlzaGVyICVpbiUgYygiTmludGVuZG8iLCJFbGVjdHJvbmljIEFydHMiLCJBY3RpdmlzaW9uIikpCnRvcF90aHJlZV9wdWJsaXNoZXIkUG9ydGFibGUgPC0gZmFjdG9yKHRvcF90aHJlZV9wdWJsaXNoZXIkUG9ydGFibGUpCnRvcF90aHJlZV9wdWJsaXNoZXJfcGxhdGZvcm0gPC0gdG9wX3RocmVlX3B1Ymxpc2hlciAlPiUKc2VsZWN0KFB1Ymxpc2hlcixHZW5yZSxQb3J0YWJsZSxHTG9iYWxfU2FsZXMpJT4lCmdyb3VwX2J5KFB1Ymxpc2hlcixHZW5yZSxQb3J0YWJsZSklPiUKc3VtbWFyaXNlKEdMb2JhbF9TYWxlcz1zdW0oR0xvYmFsX1NhbGVzKSklPiUKYXJyYW5nZShkZXNjKEdMb2JhbF9TYWxlcykpCnRvcF9uZXcgPC0gdG9wX3RocmVlX3B1Ymxpc2hlcl9wbGF0Zm9ybSU+JWdyb3VwX2J5KFB1Ymxpc2hlciklPiV0b3BfbigzKQp0b3BfbmV3JFB1Ymxpc2hlcl9nID0gZmFjdG9yKHRvcF9uZXckUHVibGlzaGVyLCBsZXZlbHM9YygiTmludGVuZG8iLCJFbGVjdHJvbmljIEFydHMiLCJBY3RpdmlzaW9uIikpCmdncGxvdCh0b3BfbmV3LCBhZXMoeD1HZW5yZSwgeT1HTG9iYWxfU2FsZXMsIGNvbG9yPVB1Ymxpc2hlcixzaGFwZT1Qb3J0YWJsZSkpICsKICBnZW9tX3BvaW50KHNpemU9MykrCnNjYWxlX2NvbG9yX2Rpc2NyZXRlKGJyZWFrcz1jKCJOaW50ZW5kbyIsIkVsZWN0cm9uaWMgQXJ0cyIsIkFjdGl2aXNpb24iKSkrCmxhYnModGl0bGU9IlRoZSB0b3AgMyBnZW5yZSBmb3IgdGhlIHRvcCAzIHB1Ymxpc2hlcnMiLGNhcHRpb249IlNhbGVzIGluIE1pbGxpb24iKSArCmdlb21fc2VnbWVudChhZXMoeD1HZW5yZSx4ZW5kPUdlbnJlLCB5PTAsIHllbmQ9R0xvYmFsX1NhbGVzKSkrCmdlb21fdGV4dChhZXMobGFiZWw9R0xvYmFsX1NhbGVzKSwgaGp1c3QgPSAtMC4zLCBzaXplID0gMi42LGZvbnRmYWNlID0gImJvbGQiLGNvbG9yPSdibGFjaycpICsKdGhlbWUoIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNyxoanVzdD0tMC41KSkgKwogIGZhY2V0X3dyYXAofiBQdWJsaXNoZXJfZywgbnJvdyA9IDUsIHNjYWxlcyA9ICdmcmVlJywgc3RyaXAucG9zaXRpb24gPSAncmlnaHQnKSsKeWxpbSgwLCBtYXgodG9wX25ldyRHTG9iYWxfU2FsZXMgKyAxMCkpK3lsYWIoIkdsb2JhbCBTYWxlcyIpKwpjb29yZF9mbGlwKCkKYGBgCgojIyMjIyMgMS5lICBHZW5yZSBmcmVxdWVuY3kgb3ZlciB0aGUgeWVhcnMgYW5kIFBsYXRmb3JtIHBvcHVsYXJpdHkgb3ZlciB0aGUgeWVhcnMKKiBIZXJlLCB0aGUgcG9wdWxhcml0eSBpcyBkZWZpbmVkIGFzIHRoZSBudW1iZXIgb2YgZ2FtZXMgcHVibGlzaGVkIG9uIGVhY2ggcGxhdGZvcm0uIEluIHRoZSBlYXJseSAxOTgwcywgdGhlcmUgd2VyZSBsaW1pdGVkIGFtb3VudCBvZiBwbGF0Zm9ybXMgaW4gdGhlIG1hcmtldCAoMjYwMCwgTkVTKSwgYnV0IGxhdGVyIG9uLCBtb3JlIGFuZCBtb3JlIHBsYXRmb3JtcyBlbWVyZ2VkLiBJdCBpcyBhbHNvIGludGVyZXN0aW5nIHRvIHNlZSB0aGF0IGRpZmZlcmVudCBwbGF0Zm9ybSB0ZW5kcyB0byBkb21pbmF0ZSB0aGUgbWFya2V0IGluIGRpZmZlcmVudCBwZXJpb2RzLCBhbmQgdGhlcmUgaXMgYSB0cmVuZCB0byBzaGlmdCBmcm9tIGxlc3MgcG9ydGFibGUgdG8gcG9ydGFibGUgb25lcy4gCgp8IFllYXJzICAgICAgICAgIHwgICAgICBNb3N0IFBvcHVsYXIgUGxhdGZvcm0gIHwgTW9zdCBQcm9maXRhYmxlIFBsYXRmb3JtIHwgICAKfC0tLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLTp8IDotLS0tLS0tLS0tOnwgICAKfCAxOTgwIC0gMTk4MiB8ICAyNjAwICB8ICAyNjAwIHwKfDE5ODN8IDI2MDAgfCBORVN8CnwgMTk4NCAtIDE5ODggfCAgTkVTICAgfCAgTkVTICB8CnwgMTk4OSAgICAgICAgfCAgR0IgICAgfCAgR0IgICB8CnwgMTk5MCAgICAgICAgfCAgTkVTICAgfCAgU05FUyB8CnwgMTk5MSAtIDE5OTQgfCAgU05FUyAgfCAgU05FUyB8CnwgMTk5NSAtIDIwMDAgfCAgUFMgICAgfCAgUFMgICB8IAp8IDIwMDEgLSAyMDA1IHwgIFBTMiAgIHwgIFBTMiAgfAp8IDIwMDYgICAgICAgIHwgIFBTMiAgIHwgIFdpbGwgfAp8IDIwMDcgLSAyMDEwIHwgIERTICAgIHwgIFdpbGwgfCAKfCAyMDExIC0gMjAxNCB8ICBQUzMgICB8ICBQUzMgIHwKfCAyMDE1IC0gMjAxNiB8ICBQUzQgICB8ICBQUzQgIHwKCmBgYHtyfQpnYW1lcyAlPiUgIGdyb3VwX2J5KFllYXIsIEdlbnJlKSAlPiUKIHN1bW1hcmlzZShDb3VudCA9IG4oKSkgJT4lIGFycmFuZ2UoWWVhciwgZGVzYyhDb3VudCkpICU+JQogc3ByZWFkKGtleSA9IEdlbnJlLCB2YWx1ZSA9IENvdW50LCBmaWxsID0gMCkgJT4lCiBnYXRoZXIoMjoxMywga2V5ID0gIkdlbnJlIiwgdmFsdWUgPSAiQ291bnQiICkgJT4lCiBhcnJhbmdlKFllYXIsIGRlc2MoQ291bnQpKSAtPiBHZW5yZVBvcAogZ2dwbG90KEdlbnJlUG9wLCBhZXMoeCA9IEdlbnJlLCB5ID0gQ291bnQpKSArCiAgICAgICAgICBnZW9tX3BvaW50KGFlcyhmcmFtZSA9IFllYXIsIGNvbG9yID0gR2VucmUsIHNpemUgPSBDb3VudCkpICsgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTY1LCB2anVzdD0wLjUpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKwogc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLG1heChHZW5yZVBvcCRDb3VudCksNTApKSsKICAgZ2d0aXRsZSgiR2VucmUgZnJlcXVlbmN5IG92ZXIgdGhlIHllYXJzIiktPiBwcG4zCmdncGxvdGx5KHBwbjMpCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9OCwgd2FybmluZz1GQUxTRX0KZ2FtZXMgJT4lICBncm91cF9ieShZZWFyLCBQbGF0Zm9ybSkgJT4lCiBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JSBhcnJhbmdlKFllYXIsIGRlc2MoY291bnQpKSAlPiUKIHNwcmVhZChrZXkgPSBQbGF0Zm9ybSwgdmFsdWUgPSBjb3VudCwgZmlsbCA9IDApICU+JQogZ2F0aGVyKDI6MzIsIGtleSA9ICJQbGF0Zm9ybSIsIHZhbHVlID0gImNvdW50IiApICU+JQogYXJyYW5nZShZZWFyLCBkZXNjKGNvdW50KSkgLT4gUGxhdGZvcm1Qb3AKIGdncGxvdChQbGF0Zm9ybVBvcCwgYWVzKHggPSBQbGF0Zm9ybSwgeSA9IGNvdW50KSkgKwogICAgICAgICAgZ2VvbV9wb2ludChhZXMoZnJhbWUgPSBZZWFyLCBjb2xvciA9IFBsYXRmb3JtLCBzaXplID0gY291bnQpKSArICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT02NSwgdmp1c3Q9MC41KSwgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsKIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCxtYXgoUGxhdGZvcm1Qb3AkY291bnQpLDUwKSkrCiAgZ2d0aXRsZSgiUGxhdGZvcm0gcG9wdWxhcml0eSBvdmVyIHRoZSB5ZWFycyIpIC0+IHBwbjIKZ2dwbG90bHkocHBuMikKYGBgCgoKIyMjIDIuIFJlZ2lvbmFsIHRyZW5kcyBhbmQgYW5hbHlzaXMgCiMjIyMjIyAyLmEgVG9wIDMgYmVzdCBzZWxsaW5nIHBsYXRmb3JtIGJ5IHJlZ2lvbnMKKiBXZSBzdHVkaWVkIHRoZSByZWdpb25hbCB0cmVuZHMgYnkgbG9va2luZyBhdCB0aGUgdG9wIHBsYXRmb3JtcyBmb3IgZWFjaCByZWdpb24gYXMgc2hvd24gZnJvbSB0aGUgYmFyIGNoYXJ0LgpgYGB7ciBlY2hvPVR9CmdhbWVzIDwtIGdhbWVzWyEoZ2FtZXMkWWVhciAlaW4lIGMoIk4vQSIsICIyMDE3IiwgIjIwMjAiKSksXQpnYW1lcyA8LSBnYW1lcyAlPiUgZ2F0aGVyKFJlZ2lvbiwgUmV2ZW51ZSwgNzoxMCkgCmdhbWVzJFJlZ2lvbiA8LSBmYWN0b3IoZ2FtZXMkUmVnaW9uKQoKbXl0aGVtZV8xIDwtIGZ1bmN0aW9uKCkgewogIAogcmV0dXJuKHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSAxMCwgdmp1c3QgPSAwLjQpLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwgdmp1c3QgPSAyKSxheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCB2anVzdCA9IC0wLjM1KSkpCiAgCn0KCm15dGhlbWVfMiA8LSBmdW5jdGlvbigpIHsKICAKIHJldHVybih0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIHZqdXN0ID0gMC40KSwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIHZqdXN0ID0gMiksYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgdmp1c3QgPSAtMC4zNSkpKQogIAp9CgpteWNvbG9ycyA8LSBjKCIjNzcxQzE5IiwgIiNBQTM5MjkiLCAiIzhFOUNBMyIsICIjNTU2NjcwIiwgIiMwMDAwMDAiLCAiI0UyNTAzMyIsICIjRjI3MzE0IiwgIiNGOEEzMUIiLCAiI0UyQzU5RiIsICIjQjZDNUNDIiwiIzc3MUMxOSIsICIjQUEzOTI5IiwgIiM4RTlDQTMiLCAiIzU1NjY3MCIsICIjMDAwMDAwIiwgIiNFMjUwMzMiLCAiI0YyNzMxNCIsICIjRjhBMzFCIiwgIiNFMkM1OUYiLCAiI0I2QzVDQyIsIiM3NzFDMTkiLCAiI0FBMzkyOSIsICIjOEU5Q0EzIiwgIiM1NTY2NzAiLCAiIzAwMDAwMCIsICIjRTI1MDMzIiwgIiNGMjczMTQiLCAiI0Y4QTMxQiIsICIjRTJDNTlGIiwgIiNCNkM1Q0MiLCIjOEU5Q0EzIikKCgp0b3BfcGxhdGZvcm1fcmVnaW9uIDwtIGdhbWVzICU+JQogICAgICAgICAgICAgZ3JvdXBfYnkoUmVnaW9uLCBQbGF0Zm9ybSkgJT4lCiAgICAgICAgICAgICBzdW1tYXJpemUoUmV2ZW51ZSA9IHN1bShSZXZlbnVlKSkgJT4lCiAgICAgICAgICAgICBhcnJhbmdlKGRlc2MoUmV2ZW51ZSkpICU+JQogICAgICAgICAgICAgdG9wX24oMykKCnRlZCA8LSBnZ3Bsb3QodG9wX3BsYXRmb3JtX3JlZ2lvbiwgYWVzKFJlZ2lvbiwgUmV2ZW51ZSwgZmlsbCA9IFBsYXRmb3JtKSkgKyAKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSAgKwogIGdndGl0bGUoIlRvcCAzIGJlc3Qgc2VsbGluZyBwbGF0Zm9ybSBieSByZWdpb25zIikgKwogIHlsYWIoIlJldmVudWUgaW4gTWlsbGlvbnMiKSArCiAgeGxhYigiUmVnaW9uIikgKwogIG15dGhlbWVfMigpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjOEU5Q0EzIiwiI0Y4QTMxQiIsICIjQUEzOTI5IiwgIiNFMjUwMzMiLCAiI0UyQzU5RiIsICIjNTU2NjcwIikpCmdncGxvdGx5KHRlZCkKYGBgCgojIyMjIyMgMi5iIFRvcCAzIGJlc3Qgc2VsbGluZyBwdWJsaXNoZXIgYnkgcmVnaW9ucwoqIFdlIHN0dWRpZWQgdGhlIHJlZ2lvbmFsIHRyZW5kcyBieSBsb29raW5nIGF0IHRoZSB0b3AgMyBiZXN0IHNlbGxpbmcgcHVibGlzaGVycyBmb3IgZWFjaCByZWdpb24uCmBgYHtyIGVjaG89VFJVRSxyZXN1bHRzPUYsZmlnLndpZHRoPTEwfQp0b3BfZ2VucmVzX3JlZ2lvbiA8LSBnYW1lcyAlPiUKICAgICAgICAgICAgIGdyb3VwX2J5KFJlZ2lvbiwgUHVibGlzaGVyKSAlPiUKICAgICAgICAgICAgIHN1bW1hcml6ZShSZXZlbnVlID0gc3VtKFJldmVudWUpKSAlPiUKICAgICAgICAgICAgIGFycmFuZ2UoZGVzYyhSZXZlbnVlKSkgJT4lCiAgICAgICAgICAgICB0b3BfbigzKQoKdGVkMiA8LSBnZ3Bsb3QodG9wX2dlbnJlc19yZWdpb24sIGFlcyhSZWdpb24sIFJldmVudWUsIGZpbGwgPSBQdWJsaXNoZXIpKSArIAogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICArCiAgZ2d0aXRsZSgiVG9wIDMgYmVzdCBzZWxsaW5nIHB1Ymxpc2hlciBieSByZWdpb24iKSArCiAgeWxhYigiU2FsZXMgaW4gTWlsbGlvbnMiKSArCiAgeGxhYigiUmVnaW9uIikgKwogIG15dGhlbWVfMigpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCmdncGxvdGx5KHRlZDIpCmBgYAoKIyMjIyMjIDIuYyBCZXN0IHNlbGxpbmcgZ2VucmUgZm9yIHBhcnRpY3VsYXIgcmVnaW9ucyAKKlRoaXMgaGVhdCBtYXAgaWRlbnRmaWVzIHRoZSB0b3Agc2VsbGluZyBnZW5yZXMgZm9yIGVhY2ggcmVnaW9uIGJ5IGRpc3BsYXlpbmcgYSBkZWVwZXIgY29sb3IgKHB1cnBsZSkgZm9yIGdlbnJlcyB3aXRoIGhpZ2ggcmV2ZW51ZXMuCmBgYHtyIGVjaG89VFJVRSxmaWcud2lkdGg9MTAsZmlnLmhlaWdodD01LHJlc3VsdHM9Rn0KeWVhcl9nZW5yZSA8LSBnYW1lcyAlPiUgCiAgICAgICAgICAgICAgICBncm91cF9ieShZZWFyLCBHZW5yZSwgUmVnaW9uKSAlPiUgCiAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShUb3RhbFJldmVudWUgPSBzdW0oUmV2ZW51ZSkpIAogICAgICAgICAgICAgICAgCgpnZ3Bsb3QoeWVhcl9nZW5yZSwgYWVzKFllYXIsIEdlbnJlLCBmaWxsID0gVG90YWxSZXZlbnVlKSkgKwogICAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIikgKwogICAgZ2d0aXRsZSgiICAgICAgICAgICAgICAgICAgICAgICBCZXN0IHNlbGxpbmcgZ2VucmUgZm9yIHBhcnRpY3VsYXIgcmVnaW9ucyIpICsgCiAgICBmYWNldF93cmFwKHZhcnMoUmVnaW9uKSwgbmNvbCA9IDQpICsKdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSkrCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93PSJwaW5rIiwgaGlnaD0gInB1cnBsZSIpKwogICAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3c9InBpbmsiLCBoaWdoPSAicHVycGxlIikKYGBgCgojIyMjIyMgMi5kIFRvcCAzIGJlc3Qgc2VsbGluZyBnZW5yZSBieSByZWdpb24KKiBXZSBzdHVkaWVkIHRoZSByZWdpb25hbCB0cmVuZHMgYnkgbG9va2luZyBhdCB0aGUgdG9wIDMgYmVzdCBzZWxsaW5nIGdlbnJlcyBmb3IgZWFjaCByZWdpb24uCmBgYHtyIGVjaG89VFJVRSxyZXN1bHRzPUYsZmlnLndpZHRoPTh9CnRvcF9nZW5yZXNfcmVnaW9uIDwtIGdhbWVzICU+JQogICAgICAgICAgICAgZ3JvdXBfYnkoUmVnaW9uLCBHZW5yZSkgJT4lCiAgICAgICAgICAgICBzdW1tYXJpemUoUmV2ZW51ZSA9IHN1bShSZXZlbnVlKSkgJT4lCiAgICAgICAgICAgICBhcnJhbmdlKGRlc2MoUmV2ZW51ZSkpICU+JQogICAgICAgICAgICAgdG9wX24oMykKCnRlZDIgPC0gZ2dwbG90KHRvcF9nZW5yZXNfcmVnaW9uLCBhZXMoUmVnaW9uLCBSZXZlbnVlLCBmaWxsID0gR2VucmUpKSArIAogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICArCiAgZ2d0aXRsZSgiVG9wIDMgYmVzdCBzZWxsaW5nIGdlbnJlIGJ5IHJlZ2lvbiIpICsKICB5bGFiKCJSZXZlbnVlIGluIE1pbGxpb25zIikgKwogIHhsYWIoIlJlZ2lvbiIpICsKICBteXRoZW1lXzIoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpCgpnZ3Bsb3RseSh0ZWQyKQpgYGAKCgojIyMgMyBJbnZlc3RtZW50IG9wdGlvbnMgYW5kIHJlY29tbWVuZGF0aW9ucyAKIyMjIyMjIDMuYSBHbG9iYWwgc2FsZXMgcHJvcG9ydGlvbiBieSByZWdpb24gCiogRm9yIHRoZSBtb3N0IHBhcnQgd2Ugc2VlIHRoYXQgdGhlIE5vcnRoIEFtZXJpY2EgYWNjb3VudHMgZm9yIHRoZSBoaWdoZXN0IHByb3BvcnRpb24gb2YgZ2xvYmFsIHNhbGVzLiBXZSBjYW4gYWxzbyBzZWUgdGhhdCBFdXJvcGVhbiBzYWxlcyBhcmUgb24gYW4gaW5jbGluZSBhbmQgYWN0dWFsbHkgc3VycGFzcyBOb3J0aCBhbWVyaWNhbiBzYWxlcyBieSB0aGUgeWVhciAyMDE1LTIwMTYuIEV2ZW4gdGhvdWdoIEphcGFuJ3MgcHJvcG9ydGlvbiBvZiBHbG9iYWwgc2FsZXMgc2VlbSB0byBiZSBkZWNsaW5pbmcgaW4gdGhlIHBhc3QgeWVhcnMsIGZvciB0aGUgbW9zdCByZWNlbnQgeWVhcnMgaXQgc2VlbXMgdG8gYmUgc3RlYWRpbHkgaW5jbGluaW5nLiAKYGBge3IgZWNobz1ULHJlc3VsdHM9Rn0KZ2FtZXMgPC0gcmVhZF9jc3YoImdhbWVzLmNzdiIpIApkZl90cmlhbCA8LSBkYXRhX2ZyYW1lKHNvcnQoZ2FtZXMkWWVhciksIE5BX1NhbGVzID0gZ2FtZXMkTkFfU2FsZXMsIGdhbWVzJEVVX1NhbGVzLAogICAgICAgICAgICAgICAgICAgICAgZ2FtZXMkSlBfU2FsZXMsIGdhbWVzJE90aGVyX1NhbGVzLCBnYW1lcyRHTG9iYWxfU2FsZXMpCmdhbWVzMyA8LSBnYW1lcyAlPiUKIHNlbGVjdChZZWFyLCBOQV9TYWxlcywgRVVfU2FsZXMsIEpQX1NhbGVzLCBPdGhlcl9TYWxlcyxHTG9iYWxfU2FsZXMpICU+JQogZ3JvdXBfYnkoWWVhcikgJT4lCiBzdW1tYXJpc2UoTkFfc2FsZXNfcHJvcCA9IHN1bShOQV9TYWxlcykvc3VtKEdMb2JhbF9TYWxlcyksCiAgICAgICAgICAgRVVfc2FsZXNfcHJvcCA9IHN1bShFVV9TYWxlcykvc3VtKEdMb2JhbF9TYWxlcyksCiAgICAgICAgICAgSlBfc2FsZXNfcHJvcCA9IHN1bShKUF9TYWxlcykvc3VtKEdMb2JhbF9TYWxlcyksCiAgICAgICAgICAgT3RoZXJfc2FsZXNfcHJvcCA9IHN1bShPdGhlcl9TYWxlcykvc3VtKEdMb2JhbF9TYWxlcyksCiAgICAgICAgICAgR2xvYmFsX3NhbGVzX3Byb3AgPSBzdW0oR0xvYmFsX1NhbGVzKS9zdW0oR0xvYmFsX1NhbGVzKSkKbXljb2xvcnMgPC0gYygiIzc3MUMxOSIsICIjQUEzOTI5IiwgIiM4RTlDQTMiLCAiIzU1NjY3MCIsICIjMDAwMDAwIiwgIiNFMjUwMzMiLCAiI0YyNzMxNCIsICIjRjhBMzFCIiwgIiNFMkM1OUYiLCAiI0I2QzVDQyIpCnJlZ2lvbnMgPC0gYyggImRhcmtncmVlbiIgPSAiTm9ydGggQW1lcmljYSIsICJibHVlIiA9ICJFdXJvcGUiICwgICJzaWVubmEiID0gIkphcGFuIiAsICJvcmFuZ2UiID0gIk90aGVyIFJlZ2lvbnMiLCAiYmxhY2siID0gIkdsb2JhbCIpCgpnZ3Bsb3QoZ2FtZXMzLGFlcyh4PVllYXIpKSsKICBnZW9tX2xpbmUoYWVzKHkgPSBOQV9zYWxlc19wcm9wICxjb2xvciA9ICIjNzcxQzE5IikpKwogIGdlb21fbGluZShhZXMoeSA9IEVVX3NhbGVzX3Byb3AgLCBjb2xvciA9ICIjQjZDNUNDIikpKwogIGdlb21fbGluZShhZXMoeSA9IEpQX3NhbGVzX3Byb3AsIGNvbG9yID0gIiNFMjUwMzMiICkpKwogIGdlb21fbGluZShhZXMoeSA9IE90aGVyX3NhbGVzX3Byb3AsIGNvbG9yID0gIiNFMkM1OUYiKSkrCiAgZ2VvbV9saW5lKGFlcyh5ID0gR2xvYmFsX3NhbGVzX3Byb3AsIGNvbG9yID0gImJsYWNrIikpKwogIGxhYnModGl0bGUgPSAiU2FsZXMgcGVyIHJlZ2lvbiBmcm9tIDE5ODAtMjAxNiIsIHkgPSAiUGVyY2VudGFnZSBvZiBnbG9iYWwgc2FsZXMiKSsKICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZSA9ICJSZWdpb25zIiwgdmFsdWVzID0gYyggImRhcmtncmVlbiIsICJibHVlIiwgInNpZW5uYSIgLCAib3JhbmdlIiwgImJsYWNrIiksbGFiZWxzPWMoIk5vcnRoIEFtZXJpY2EiLCAiRXVyb3BlIiAsICJKYXBhbiIgLCAiT3RoZXIgUmVnaW9ucyIsICJHbG9iYWwiKSkKYGBgCgojIyMjIyMgMy5iIFN1bW1hcnkgCgp8IE9wdGlvbiB8ICAgICBOb3J0aCBBbWVyaWNhICB8IEV1cm9wZSB8IEphcGFuIHwKfC0tLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLTp8IDotLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLXwKfFB1Ymxpc2hlcnwgTmludGVuZG8gfCBOaW50ZW5kbyB8TmludGVuZG8gfAp8UGxhdGZvcm0gfCBYMzYwIHwgUFMzIHwgRFMgfAp8R2VucmUgICB8IEFjdGlvbiB8IEFjdGlvbiB8IFJvbGUtUGxheWluZ3wKCgoKIyMjIEFwcGVuZGl4CgojIyMjIyMgRGF0YSBFeHBsb3JhdGlvbi4gCmBgYHtyIGVjaG89VFJVRSxmaWcuaGVpZ2h0PTh9CmdncGxvdChnYW1lcywgYWVzKHg9WWVhciwgZmlsbD0uLmNvdW50Li4pKSArCiAgICBnZW9tX2JhcigpKwogICAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93PSIjNzcxQzE5IiwgaGlnaD0gIiNGMjczMTQiKSsKICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93PSIjNzcxQzE5IiwgaGlnaD0gIiNGMjczMTQiKSsKICAgIGxhYnModGl0bGU9Ik51bWJlciBvZiBHYW1lcyBSZWxlYXNlZCBldmVyeSBZZWFyIiwgeD0gIlllYXIiLCAKICAgICAgICAgeT0gIlRvdGFsIE51bWJlciBvZiBHYW1lcyIpKwogICAgZ2VvbV90ZXh0KHN0YXQ9J2NvdW50JyxhZXMobGFiZWw9Li5jb3VudC4uKSwgaGp1c3Q9LTAuMSxjb2xvcj0iYmxhY2siLCBzaXplPTIuNSkrCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTk4MDoyMDE2KSArIHRoZW1lX21pbmltYWwoKSsKICBjb29yZF9mbGlwKCkKYGBgCgojIyMjIyMgRGF0YSBFeHBsb3JhdGlvbiAyIApgYGB7cn0Kb3B0aW9ucyhzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpClBvcnRhYmxlIDwtIGZ1bmN0aW9uKGRmKSB7CiBsZW4gPC0gbGVuZ3RoKGRmJFBsYXRmb3JtKQogbmV3X3ZlYyA8LSB2ZWN0b3IobW9kZSA9ICJudW1lcmljIiwgbGVuZ3RoID0gbGVuKQogcHJvdHZlYyA8LSBjKCJEUyIsICJHQiIsICIzRFMiLCAiR0JBIikKIGZvciAoaSBpbiAxOmxlbikgIHsKICAgaWYgKGRmJFBsYXRmb3JtW2ldICVpbiUgcHJvdHZlYykgewogICAgIG5ld192ZWNbaV0gPC0gMQogICB9IGVsc2UgewogICAgIG5ld192ZWNbaV0gPC0gMAogICB9CiB9CiByZXR1cm4obmV3X3ZlYykKfQpnYW1lcyRQb3J0YWJsZSA8LSBQb3J0YWJsZShnYW1lcykKCmdhbWVzMjwtIGdhbWVzCgpnYW1lczIgJT4lCiB0cmFuc211dGUoWWVhcjIwMDggPSBjdXQoWWVhciwgYnJlYWtzID0gYygxOTgwLCAyMDA4LCAyMDE3KSwKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCZWZvcmUgMjAwOCIsICJBZnRlciAyMDA4IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZS5sb3dlc3QgPSBUUlVFLCByaWdodCA9IEZBTFNFKSwKICAgICAgICAgICBQb3J0YWJsZSA9IGZhY3RvcihQb3J0YWJsZSksCiAgICAgICAgICAgU2FsZXMgPSBHTG9iYWxfU2FsZXMpICU+JQogZ3JvdXBfYnkoWWVhcjIwMDgsIFBvcnRhYmxlKSAlPiUKIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgLT4gZ2FtZXMzCgpnZ3Bsb3QoZ2FtZXMzKSArCiBnZW9tX2JhcihhZXMoeCA9IFBvcnRhYmxlICwgeSA9IGNvdW50LCBmaWxsID0gWWVhcjIwMDgpLAogICAgICAgICAgICAgICAgcG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogbGFicyhzdWJ0aXRsZT0iUG9ydGFibGUgVnMuIE5vbi1Qb3J0YWJsZSIsIHg9ICJUeXBlIiwKICAgICAgICB5PSAiVG90YWwgTnVtYmVyIG9mIEdhbWVzIFJlbGVhc2VkIikgKwogdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpIApgYGAKCiMjIyMjIyBEYXRhIEV4cGxvcmF0aW9uIDMgCmBgYHtyIGVjaG89VFJVRSxmaWcud2lkdGg9MTAsZmlnLmhlaWdodD01LHJlc3VsdHM9RiwgZmlnLndpZHRoPSAxMH0Kb2sgPC0gZ2FtZXMgJT4lIHNlbGVjdChZZWFyLEdMb2JhbF9TYWxlcyxHZW5yZSklPiVncm91cF9ieShZZWFyLEdlbnJlKSU+JQogIHN1bW1hcmlzZShUb3RhbF9zYWxlcz1zdW0oR0xvYmFsX1NhbGVzKSkgCm9rMSA8LSBhcnJhbmdlKG9rLCBkZXNjKFllYXIpKQoKcGxvdF9seShvazEsIHggPSB+VG90YWxfc2FsZXMsIHkgPSB+R2VucmUsIHogPSB+WWVhcikgJT4lIGxheW91dCggdGl0bGUgPSJTYWxlcyBieSBnZW5yZSBmcm9tIDE5ODAgLSAyMDE2IikgJT4lCiAgYWRkX21hcmtlcnMoY29sb3IgPSB+R2VucmUsIHNpemUgPSAwLjUpCgpgYGAKCgoKCgoKCgo=